﻿/*
(c) 2010 - Open Source Business Foundation e. V. (www.osbf.de)
This software is provided under Microsoft Reciprocal License (Ms-RL)
(http://www.microsoft.com/opensource/licenses.mspx#Ms-RL)
All other rights reserved
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Net;
using System.Web.UI;
using System.Web.UI.WebControls;
using MicroFormatProcessing;
using System.Diagnostics;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using System.Text;

namespace MicroFormatWebRole
{
    /// <summary>
    /// C# part of the Browse asp
    /// </summary>

    public partial class Browse : System.Web.UI.Page
    {
        class MicroFormatNameComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                int result = 1;
                if ((x != null) && (y != null))
                {
                    MicroFormat microFormatX = (MicroFormat)x;
                    MicroFormat microFormatY = (MicroFormat)y;
                    if (microFormatX.Name != null)
                        result = microFormatX.Name.CompareTo(microFormatY.Name);
                }
                return result;
            }
        }

        private Session MySession;
        private string MyUser;
        private string MyTag;
        private bool PageLoading;
        private bool EditEnabled;

        protected void Page_Load(object sender, EventArgs e)
        {
            this.PageLoading = true;
            this.MyTag = Request["tag"];
            this.MyUser = Request["user"];

            string sessionId = Request["sessionId"];
            if (sessionId == null)
            {
                sessionId = (Request.Cookies["session"] != null) ? Request.Cookies["session"]["id"] : null;
            }
            if (sessionId != null)
            {
                this.MySession = UserUtil.GetSesssion(sessionId);
            }
            if ((this.MyUser == null) && (this.MySession != null))
            {
                this.MyUser = this.MySession.UserId;
            }

            this.EditEnabled = ((this.MySession != null) && (this.MySession.UserId.Equals(this.MyUser)));
            if (this.EditEnabled) {
                HeaderSectionLeft2.Visible = true;
                HeaderSectionLeft3.Visible = false;
                HeaderSectionRight3.Visible = true;
                LoginLabel.Text = String.Format("Logged in as {0}", this.MyUser);
            } else {
                HeaderSectionLeft2.Visible = false;
                HeaderSectionLeft3.Visible = true;
                HeaderSectionRight3.Visible = false;
            }

            // bugfix for otherwise mising generated <script>
            ClientScript.GetPostBackEventReference(new PostBackOptions(MfDefinitionGridView));
            
            // fix url for rewrite and nice bookmarking
            form1.Action = CreateBrowseUrl(this.MyUser, this.MyTag);

            if (this.EditEnabled && (this.MyUser != null) && (this.MyTag != null) && (Request["delete"] != null))
            {
                DoDelete(this.MyUser, this.MyTag, Request["delete"]);
            }
            else
            {



                // Load data for the DropDownList control only once, when the page is first loaded.
                if (!IsPostBack)
                {
                    MfDefinitionSection.Visible = false;
                    ContentSection.Visible = false;
                    UsernameTextbox.Text = this.MyUser;

                    MfUserTagGridView.DataSource = CreateMfUserTagGridViewDataSource();
                    MfUserTagGridView.DataBind();

                    int selectedRow = -1;
                    if (this.MyTag != null)
                    {
                        for (int i = 0; (selectedRow < 0) && (i < MfUserTagGridView.Rows.Count); i++)
                        {
                            if (this.MyTag.Equals(MfUserTagGridView.Rows[i].Cells[0].Text))
                            {
                                selectedRow = i;
                            }
                        }
                    }
                    if (selectedRow < 0)
                    {
                        selectedRow = 0;
                        this.MyTag = "Me";
                    }
                    MfUserTagGridView.SelectRow(selectedRow);

                    UpdateMfDefinitionFromMfUserTag();
                    if (MfDefinitionGridView.Rows.Count == 1)
                    {
                        MfDefinitionGridView.SelectRow(0);
                        UpdateMfPropertyFromMfDefinition();
                    }
                }
            }
            this.PageLoading = false;
        }

        protected void UsernameTextbox_TextChanged(Object sender, EventArgs e)
        {
            Response.Redirect(CreateBrowseUrl(UsernameTextbox.Text, null));
        }

        protected void MfUserTagGridView_SelectedIndexChanged(Object sender, EventArgs e)
        {
            if ((!this.PageLoading) && (MfUserTagGridView.Rows.Count > 0))
            {
                GridViewRow row = MfUserTagGridView.SelectedRow;
                string tag = (row != null) ? row.Cells[0].Text : null;
                Response.Redirect(CreateBrowseUrl(this.MyUser, tag));
            }
        }

        protected void MfDefinitionGridView_SelectedIndexChanged(Object sender, EventArgs e)
        {
            UpdateMfPropertyFromMfDefinition();
        }

        protected void MfUserTagGridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            RowDataBoundMouseEvents(e, MfUserTagGridView, "#E2DED6", "#F7F6F3", "White");
        }


        protected void MfPropertyGridView_RowEditing(object sender, GridViewEditEventArgs  e) {
            String value = MfPropertyGridView.Rows[e.NewEditIndex].Cells[1].Text;
        }

        protected void MfDefinitionGridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            RowDataBoundMouseEvents(e, MfDefinitionGridView, "#E2DED6", "#F7F6F3", "White");
            e.Row.Cells[5].Visible = false;
            if (!this.EditEnabled) {
                e.Row.Cells[2].Visible = false;
                e.Row.Cells[3].Visible = false;
                e.Row.Cells[4].Visible = false;
            } else {
                if (e.Row.Cells[1].Text == Constants.hCard) {
                    e.Row.Cells[3].Visible = true;
                    e.Row.Cells[4].Visible = false;
                } else {
                    e.Row.Cells[3].Visible = false;
                    e.Row.Cells[4].Visible = true;
                }
            }
        }

        private void RowDataBoundMouseEvents(GridViewRowEventArgs e, Control control, string colorSelect, string colorOdd, string colorEven)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                e.Row.Attributes["onmouseover"] = "setStyle(this, 'backgroundColor', '" + colorSelect + "')";
                if (e.Row.RowIndex % 2 > 0)
                {
                    e.Row.Attributes["onmouseout"] = "setStyle(this, 'backgroundColor', '" + colorOdd + "')";
                }
                else
                {
                    e.Row.Attributes["onmouseout"] = "setStyle(this, 'backgroundColor', '" + colorEven + "')";
                }
                e.Row.Attributes["onclick"] = ClientScript.GetPostBackClientHyperlink(control, "Select$" + e.Row.RowIndex);
            }
        }


        protected void OnNewCardButtonClick(object sender, EventArgs e) {
            Response.Redirect(String.Format("Edit.aspx?edit={0}&tag={1}&user={2}", "", this.MyTag, this.MyUser));
        }

        protected void MfPropertyGridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                if ("url".Equals(e.Row.Cells[0].Text))
                {
                    string url = e.Row.Cells[1].Text;
                    e.Row.Cells[1].Controls.Clear();
                    HyperLink link = new HyperLink();
                    link.NavigateUrl = url;
                    link.Text = url;
                    e.Row.Cells[1].Controls.Add(link);
                }
            }
        }

        private void UpdateMfDefinitionFromMfUserTag()
        {
            ContentSection.Visible = false;
            MfDefinitionSection.Visible = false;
            if ((this.MyTag != null) && (this.MyUser != null))
            {
                ArrayList microFormats = new ArrayList();
                MicroFormatRepository mfRepository = new MicroFormatRepository();
                if (Constants.EVERYTHING.Equals(this.MyTag))
                {
                    foreach (MicroFormat microFormat in mfRepository.FindByUserId(this.MyUser))
                    {
                        microFormats.Add(microFormat);
                    }
                }
                else
                {
                    TagRepository tagRepository = new TagRepository();
                    foreach (Tag tag in tagRepository.FindByUserIdAndTagName(this.MyUser, this.MyTag))
                    {
                        foreach (string reference in tag.GetReferences())
                        {
                            foreach (MicroFormat microFormat in mfRepository.FindByUserIdAndMfId(this.MyUser, reference))
                            {
                                microFormats.Add(microFormat);
                            }
                        }
                    }
                }
                microFormats.Sort(new MicroFormatNameComparer());
                MfDefinitionGridView.DataSource = CreateMfDefinitionGridDataSource(microFormats);
                MfDefinitionGridView.DataBind();
                MfDefinitionGridView.SelectRow(-1);
                if (microFormats.Count > 0)
                {
                    StringBuilder mfHtml = new StringBuilder();
                    foreach (MicroFormat microFormat in microFormats)
                    {
                        mfHtml.Append(microFormat.ToHtml());
                    }
                    MicroFormatsLiteral.Text = mfHtml.ToString();
                    MfDefinitionSection.Visible = true;
                }
            }
        }

        private void UpdateMfPropertyFromMfDefinition()
        {
            GridViewRow viewRow = MfDefinitionGridView.SelectedRow;
            if (viewRow != null)
            {
                string mfId = viewRow.Cells[5].Text;
                if (mfId != null)
                {
                    MicroFormat selectedMicroFormat = null;
                    MicroFormatRepository mfRepository = new MicroFormatRepository();
                    foreach (MicroFormat microFormat in mfRepository.FindByUserIdAndMfId(this.MyUser, mfId))
                    {
                        selectedMicroFormat = microFormat;
                    }
                    if (selectedMicroFormat != null)
                    {
                        selectedMicroFormat.DeSerializeAttributes();
                        ContentSection.Visible = true;
                        ContentTitle.Text = String.Format("{0} [{1}] Detail", selectedMicroFormat.Name, selectedMicroFormat.Type);
                        ContentDate.Text = selectedMicroFormat.FoundOnDate.ToString("yyyy'-'MM'-'dd HH':'mm':'ss");
                        ContentUrl.Text = selectedMicroFormat.FoundOnUrl;
                        ContentUrl.NavigateUrl = selectedMicroFormat.FoundOnUrl;
                        TaggedAsRepeater.DataSource = CreateTaggedAsRepeaterDataSource(selectedMicroFormat);
                        TaggedAsRepeater.DataBind();
                        MfPropertyGridView.DataSource = CreateMfPropertyGridDataSource(selectedMicroFormat);
                        MfPropertyGridView.DataBind();
                    }
                }
            }
        }

        private DataView CreateMfUserTagGridViewDataSource()
        {

            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("Tag", typeof(String)));

            if (this.MyUser != null)
            {
                TagRepository tagRepository = new TagRepository();
                List<string> tagNames = new List<string>();
                bool tagsFound = false;
                foreach (Tag tag in tagRepository.FindByUserId(this.MyUser))
                {
                    tagsFound = true;
                    if (!Constants.ME.Equals(tag.GetTagName()) && !Constants.FRIENDS.Equals(tag.GetTagName()) && !Constants.UNTAGGED.Equals(tag.GetTagName()))
                    {
                        tagNames.Add(tag.GetTagName());
                    }
                }
                if (tagsFound)
                {
                    tagNames.Sort();
                    tagNames.Insert(0, "Everything");
                    tagNames.Insert(0, "Friends");
                    tagNames.Insert(0, "Me");
                    tagNames.Add("Untagged");
                    foreach (string tagName in tagNames)
                    {
                        DataRow dr = dt.NewRow();
                        dr[0] = tagName;
                        dt.Rows.Add(dr);
                    }
                }
            }
            return new DataView(dt);
        }

        private DataView CreateMfDefinitionGridDataSource(ArrayList microFormats)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("Name", typeof(String)));
            dt.Columns.Add(new DataColumn("Type", typeof(String)));
            dt.Columns.Add(new DataColumn("Delete", typeof(String)));
            dt.Columns.Add(new DataColumn("Edit", typeof(String)));
            dt.Columns.Add(new DataColumn("Dummy", typeof(String)));
            dt.Columns.Add(new DataColumn("Id", typeof(String)));
            foreach (MicroFormat microFormat in microFormats)
            {
                DataRow dr = dt.NewRow();
                dr[0] = microFormat.Name;
                dr[1] = microFormat.Type;
                dr[2] = String.Format("delete={0}&tag={1}&user={2}", microFormat.RowKey, this.MyTag, this.MyUser);
                dr[3] = String.Format("edit={0}&tag={1}&user={2}", microFormat.RowKey, this.MyTag, this.MyUser);
                dr[4] = " ";
                dr[5] = microFormat.RowKey;

                dt.Rows.Add(dr);
            }
            return new DataView(dt);
        }

        private DataView CreateMfPropertyGridDataSource(MicroFormat microFormat)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("Property", typeof(String)));
            dt.Columns.Add(new DataColumn("Value", typeof(String)));
            if (microFormat != null)
            {
                string[] propertyNames = microFormat.GetPropertyNameArray();
                Array.Sort(propertyNames);
                foreach (string propertyName in propertyNames)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = propertyName;
                    dr[1] = microFormat.GetProperty(propertyName);
                    dt.Rows.Add(dr);
                }
            }
            return new DataView(dt);
        }



        private DataView CreateTaggedAsRepeaterDataSource(MicroFormat microFormat)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("Tag", typeof(String)));
            dt.Columns.Add(new DataColumn("Url", typeof(String)));
            DataTable mfUserTagDataTable = CreateMfUserTagGridViewDataSource().Table;
            if (microFormat != null)
            {
                foreach (string tagName in microFormat.GetTagArray())
                {
                    int selectedRow = -1;
                    for (int i = 0; (selectedRow < 0) && (i < mfUserTagDataTable.Rows.Count); i++)
                    {
                        if (tagName.Equals((string)mfUserTagDataTable.Rows[i][0]))
                        {
                            selectedRow = i;
                        }
                    }
                    if (selectedRow >= 0)
                    {
                        DataRow dr = dt.NewRow();
                        dr[0] = tagName;
                        dr[1] = ClientScript.GetPostBackClientHyperlink(MfUserTagGridView, "Select$" + selectedRow);
                        dt.Rows.Add(dr);
                    }
                }
            }
            return new DataView(dt);
        }

   
        private void DoDelete(string userId, string tagName, string mfId)
        {
            MicroFormat microFormat = null;
            MicroFormatRepository mfRepository = new MicroFormatRepository();
            foreach (MicroFormat mf in mfRepository.FindByUserIdAndMfId(userId, mfId))
            {
                microFormat = mf;
            }
            if (microFormat != null)
            {
                if (microFormat.GetTagCount() > 1)
                {
                    microFormat.RemoveTag(tagName);
                    mfRepository.Update(microFormat, false);
                }
                else
                {
                    mfRepository.Delete(microFormat, false);
                }
            }
            Tag tag = null;
            TagRepository tagRepository = new TagRepository();
            foreach (Tag t in tagRepository.FindByUserIdAndTagName(userId, tagName))
            {
                tag = t;
            }
            if (tag != null)
            {
                if (tag.GetReferenceCount() > 1)
                {
                    tag.RemoveReference(mfId);
                    tagRepository.Update(tag, false);
                }
                else
                {
                    tagRepository.Delete(tag, false);
                }
            }
            Response.Redirect(form1.Action);
        }

        private string CreateBrowseUrl(string user, string tag)
        {
            StringBuilder url = new StringBuilder();
            url.Append("Browse.aspx");
            if (user != null)
            {
                url.Append("?user=").Append(user);
                if (tag != null)
                {
                    url.Append("&tag=").Append(tag);
                }
            }
            return url.ToString();
        }
    }
}